package owlapps2012.owlToSql.base;

import java.util.ArrayList;
import java.util.HashMap;

/**
* Author: Piotr Nowara<br>
* piotrnowara@gmail.com<br>
* code made available under Mozilla Public License (http://www.mozilla.org/MPL/MPL-1.1.html)<br>
* copyright 2012, Piotr Nowara<br>
*/
public abstract class DefaultAppConfig 
{
	protected final int maxCardinality = 10;
	protected final int maxNumberOfTemporalRelations = 25;
	private ArrayList<DomainPropertyMapping> domainPropertiesMappingList = new ArrayList<DomainPropertyMapping>();
	private ArrayList<DomainClassMapping> domainClassMappingList = new ArrayList<DomainClassMapping>();
	protected String idColumn = "ID";//name of unique id of a fact, the default may be overridden
	protected String dateColumn = "DATE";//name of unique id of a fact, the default may be overridden
	protected SQLType sqlType = null;
	protected HashMap<String, String> additionalConditions = new HashMap<String, String>();//name of unique id of a fact, the default may be overridden
	protected boolean writeReport = false;

	protected DefaultAppConfig() throws Exception
	{
		this.initConf();
	}
	
	public ArrayList<DomainPropertyMapping> getDomainPropertiesMappingList() {
		return domainPropertiesMappingList;
	}
	
	protected void setDomainPropertiesMapping(ArrayList<DomainPropertyMapping> domainPropertiesMappingList) 
	{
		this.domainPropertiesMappingList = domainPropertiesMappingList;
	}
	
	public void addDomainClassMapping(DomainClassMapping m) throws Exception
	{
		if(this.getDomainClassMapping(m.getClassName()) == null)
			this.domainClassMappingList.add(m);
		else
			throw new Exception("Classes must have unique names - cannot add duplicated entry: "+ m.getClassName());
	}
	
	public DomainClassMapping getDomainClassMapping(String className)
	{
		DomainClassMapping r = null;
		for(int i=0;i<this.domainClassMappingList.size(); i++) 
		{
			DomainClassMapping m = this.domainClassMappingList.get(i);
			if(m.getClassName().equals(className))
				r = m;
		}
		return r;
	}
	
	public DomainPropertyMapping getDomainPropertyMapping(String propertyName)
	{
		DomainPropertyMapping r = null;
		for(int i=0;i<this.domainPropertiesMappingList.size(); i++) 
		{
			DomainPropertyMapping m = this.domainPropertiesMappingList.get(i);
			if(m.getPropertyName().equals(propertyName))
				r = m;
		}
		return r;
	}

	public void addDomainPropertyMapping(DomainPropertyMapping m) throws Exception
	{
		if(this.getDomainPropertyMapping(m.getPropertyName()) == null)
			this.domainPropertiesMappingList.add(m);
		else
			throw new Exception("Domain proprties must have unique names - cannot add duplicated entry: "+ m.getPropertyName());
	}
	
	public int getMaxCardinality() {
		return maxCardinality;
	}
	public int getMaxNumberOfTemporalRelations() {
		return maxNumberOfTemporalRelations;
	}
	
	protected abstract void initConf() throws Exception;

	public String getIdColumn() {
		return idColumn;
	}

	public void setIdColumn(String idField) {
		this.idColumn = idField;
	}

	public ArrayList<DomainClassMapping> getClassMappingList() {
		return domainClassMappingList;
	}

	public void setClassMappingList(ArrayList<DomainClassMapping> classMappingList) {
		this.domainClassMappingList = classMappingList;
	}

	public String getAdditionalCondition(String type) {
		return additionalConditions.get(type);
	}
	
	public String getDateColumn() {
		return dateColumn;
	}

	public void setDateColumn(String dateField) {
		this.dateColumn = dateField;
	}
	
	public SQLType getSqlType() {
		return sqlType;
	}

	public void setSqlType(SQLType sqlType) {
		this.sqlType = sqlType;
	}

	//{Q2}.{DATE_FIELD} - {Q1}.{DATE_FIELD}
	public String getDBSpecificDateDifference(String dateDiffExp) throws OwlToSqlTransformationException
	{
		if(this.sqlType == null)
			return dateDiffExp;
		else if(this.sqlType == SQLType.DB2)
			return "DAYS(".concat(dateDiffExp).concat(")").replace(" - ", ") - DAYS(");
		else if(this.sqlType == SQLType.MYSQL)
			return "TO_DAYS(".concat(dateDiffExp).concat(")").replace(" - ", ") - TO_DAYS(");
		else if(this.sqlType == SQLType.ORACLE)
			return "FLOOR(".concat(dateDiffExp).concat(")");
		else if(this.sqlType == SQLType.MSSQL)
			return "DATEDIFF(d, ".concat(dateDiffExp).concat(")").replaceFirst(" - ",", ");
		else if(this.sqlType == SQLType.POSTGRES)
			return dateDiffExp;
		else
			throw new OwlToSqlTransformationException("Unsupported SQL dialect: "+ this.sqlType.getName());
	}
	
	public boolean isWriteReport() {
		return writeReport;
	}
}
